//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "can_bsp.h"
#include <string.h>

/*CAN 总管理结构体*/
typedef struct
{
	void (*Rx_IT_Callback)(unsigned int id, unsigned char* const buffer, unsigned char length);
	void (*Tx_IT_Callback)(void);
    volatile WHT_CAN_Info_t Info;
}WHT_Data_t;


static WHT_Data_t WHT_CAN1;
static WHT_Data_t WHT_CAN2;



/*CAN GPIO初始化*/
static void WHT_CAN_BSP_GPIO_Init(const WHT_CAN_Config_t* config)
{
#if 1
    WHT_GPIO_BSP.WHT_Set_Clock(PortA, ENABLE);
    WHT_GPIO_BSP.WHT_Set_State(PortA, Pin11 | Pin12, Hig);
    WHT_GPIO_BSP.WHT_Set_Mode(PortA, Pin12, Mode_AF_PP);
	WHT_GPIO_BSP.WHT_Set_Mode(PortA, Pin11, Mode_IPU);
#else
    WHT_GPIO_BSP.WHT_Set_Clock(PortB, ENABLE);
    WHT_GPIO_BSP.WHT_Set_State(PortB, Pin8 | Pin9, Hig);
    WHT_GPIO_BSP.WHT_Set_Mode(PortB, Pin9, Mode_AF_PP);
	WHT_GPIO_BSP.WHT_Set_Mode(PortB, Pin8, Mode_IPU);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO ,ENABLE);//重映射使能AFIO时钟
	//使用PB8 9引脚的第二功能
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO ,DISABLE);//重映射失能AFIO时钟
#endif
}
/*CAN 中断优先级配置*/
static void NVIC_Configuration(WHT_CAN_enum name, const WHT_CAN_Config_t* config)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	/* 嵌套向量中断控制器组选择 */
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

	/* 抢断优先级*/
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = config->PreemptionPriority;
	/* 子优先级 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = config->SubPriority;
	/* 使能中断 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

	/* 配置中断源 */
#ifdef STM32F10X_CL
	if (name == CAN_1)
	{
		NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
		NVIC_Init(&NVIC_InitStructure);
	}
	else if (name == CAN_2)
	{
		NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = CAN2_SCE_IRQn;
		NVIC_Init(&NVIC_InitStructure);
	}
#else
	if (name == CAN_1)
	{
		NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn;
		NVIC_Init(&NVIC_InitStructure);
		NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
		NVIC_Init(&NVIC_InitStructure);
	}
#endif /* STM32F10X_CL */
	else
	{
		return;
	}
}
/*CAN 滤波器配置*/
static void WHT_CAN_BSP_Filter_Config(const WHT_CAN_Config_t* config)
{
	CAN_FilterInitTypeDef CAN_FilterInitStruct;

	CAN_FilterInitStruct.CAN_FilterActivation     = ENABLE;                //打开过滤器
	CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;      //滤波器给FIFO0
	CAN_FilterInitStruct.CAN_FilterScale          = CAN_FilterScale_32bit; //采用32位掩码模式
	CAN_FilterInitStruct.CAN_FilterMode           = CAN_FilterMode_IdMask; //采用掩码模式

	/* 滤波器0 对于本机通信 */
	CAN_FilterInitStruct.CAN_FilterNumber         = 0;                     //过滤器组0 这里可设0-13
	// CAN_FilterInitStruct.CAN_FilterIdHigh     = (config->ID << 3 | CAN_Id_Extended | CAN_RTR_Data) >> 16;     //扩展ID 数据帧模式
	// CAN_FilterInitStruct.CAN_FilterIdLow      = (config->ID << 3 | CAN_Id_Extended | CAN_RTR_Data) & 0xFFFF;
	// CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xffff;
	// CAN_FilterInitStruct.CAN_FilterMaskIdLow  = 0xffff & (~(0x0f<<3)); //忽略ID的低4bit
    CAN_FilterInitStruct.CAN_FilterIdHigh     = (config->ID << 21 | CAN_Id_Standard | CAN_RTR_Data) >> 16;     //标准ID 数据帧模式
    CAN_FilterInitStruct.CAN_FilterIdLow      = (config->ID << 21 | CAN_Id_Standard | CAN_RTR_Data);
	CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xffff & (~(0x0f<<5)); //忽略ID的低4bit
	CAN_FilterInitStruct.CAN_FilterMaskIdLow  = 0xffff;
	CAN_FilterInit(&CAN_FilterInitStruct);

	/* 滤波器1 对于心跳包 */
	CAN_FilterInitStruct.CAN_FilterNumber         = 1;                     //过滤器组1 这里可设0-13
    CAN_FilterInitStruct.CAN_FilterIdHigh   = (0x700 << 21 | CAN_Id_Standard | CAN_RTR_Data) >> 16;     //标准ID 数据帧模式
    CAN_FilterInitStruct.CAN_FilterIdLow    = (0x700 << 21 | CAN_Id_Standard | CAN_RTR_Data) & 0xFFFF;
	CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xffff;
	CAN_FilterInitStruct.CAN_FilterMaskIdLow  = 0xffff;
	CAN_FilterInit(&CAN_FilterInitStruct);
}
/*CAN 配置*/
static ErrorStatus WHT_CAN_BSP_Config(WHT_CAN_enum name, const WHT_CAN_Config_t* config)
{
	CAN_InitTypeDef CAN_InitStruct;
	WHT_Data_t* WHT_Data;

	if (name == CAN_1)
	{
		WHT_Data = &WHT_CAN1;
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
	}
	else if (name == CAN_2)
	{
		WHT_Data = &WHT_CAN2;
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
	}
	else
	{
		return ERROR;
	}

	WHT_Data->Tx_IT_Callback = config->Tx_IT_Callback;
	WHT_Data->Rx_IT_Callback = config->Rx_IT_Callback;
	memset(&WHT_Data->Info.Error_State, 0, sizeof(WHT_CAN_Error_State_t));
	WHT_Data->Info.TRx_Error_State = CAN_No_Error;
	WHT_Data->Info.TRx_State = CAN_TRx_Idle;

	CAN_DeInit((CAN_TypeDef*)name);
	WHT_CAN_BSP_GPIO_Init(config);
	NVIC_Configuration(name, config);

	CAN_StructInit(&CAN_InitStruct);
	CAN_InitStruct.CAN_ABOM = ENABLE;  //自动总线关闭管理功能
	CAN_InitStruct.CAN_AWUM = ENABLE;  //自动总线唤醒功能
	CAN_InitStruct.CAN_Mode = CAN_Mode_Normal;/////CAN_Mode_LoopBack;//CAN_Mode_Normal;//调试时建议使用回环模式，调试完再改成NORMAL
	CAN_InitStruct.CAN_NART = ENABLE;  //错误重传
	CAN_InitStruct.CAN_RFLM = DISABLE; //接收FIFO满后覆盖旧报文
	CAN_InitStruct.CAN_TTCM = DISABLE; //关闭时间触发通信功能
	CAN_InitStruct.CAN_TXFP = DISABLE; //按ID优先级发送 ENABLE按照先后顺序发送

	//配置速率
	CAN_InitStruct.CAN_BS1 = CAN_BS1_5tq;
	CAN_InitStruct.CAN_BS2 = CAN_BS2_3tq;
	CAN_InitStruct.CAN_SJW = CAN_SJW_2tq;
	CAN_InitStruct.CAN_Prescaler = config->prescaler; //(72mhz / 2) / (5 + 3 + 1) = 4mhz  4mhz / 16 = 250khz

	CAN_Init((CAN_TypeDef*)name, &CAN_InitStruct);
	WHT_CAN_BSP_Filter_Config(config);

	CAN_ITConfig((CAN_TypeDef*)name, CAN_IT_FMP0, ENABLE);//接收邮箱非空中断
	CAN_ITConfig((CAN_TypeDef*)name, CAN_IT_TME, DISABLE);//发送邮箱空中断

    // 使能所有错误中断
    CAN_ITConfig((CAN_TypeDef*)name, CAN_IT_EWG | CAN_IT_EPV | CAN_IT_BOF | CAN_IT_LEC, ENABLE);//ISO 26262 功能安全标准
	
	return SUCCESS;
}


/*CAN 普通发送数据*/
static ErrorStatus WHT_CAN_BSP_TxMessage(WHT_CAN_enum name, WHT_CAN_Message_t* tx_message, unsigned int timeout_ms)
{
	CanTxMsg TxMessage;
	WHT_Data_t* WHT_Data;
	unsigned char TransmitMailbox;
	
	if (name == CAN_1)
	{
		WHT_Data = &WHT_CAN1;
	}
	else if (name == CAN_2)
	{
		WHT_Data = &WHT_CAN2;
	}
	else
	{
		return ERROR;
	}
	
	WHT_Data->Info.TRx_State = CAN_TRx_Busy;
	WHT_Data->Info.TRx_Error_State = CAN_No_Error;

	TxMessage.StdId = tx_message->ID;
	TxMessage.ExtId = tx_message->ID;
	TxMessage.RTR = CAN_RTR_Data;
	TxMessage.IDE = CAN_Id_Standard; //CAN_Id_Standard 标准帧 CAN_Id_Extended 扩展帧
	TxMessage.DLC = tx_message->length;
	memcpy(TxMessage.Data, tx_message->buffer, tx_message->length);

	CAN_ITConfig((CAN_TypeDef*)name, CAN_IT_TME, DISABLE); //发送邮箱空中断

	// 获取发送邮箱
	while (1)
	{
		TransmitMailbox = CAN_Transmit((CAN_TypeDef*)name, &TxMessage);
		if (TransmitMailbox == CAN_TxStatus_NoMailBox)
		{
			if (timeout_ms > 0)
			{
				timeout_ms--;
				WHT_Delay_ms(1);
			}
			else
			{
				WHT_Data->Info.TRx_State = CAN_TRx_Idle;
				return ERROR;
			}
		}
		else
		{
			break;
		}
	}

	WHT_Data->Info.TRx_State = CAN_TRx_Idle;
	return SUCCESS;// 发送成功
}

/*CAN 中断发送数据*/
static ErrorStatus WHT_CAN_BSP_TxMessage_IT(WHT_CAN_enum name, WHT_CAN_Message_t* tx_message)
{
	CanTxMsg TxMessage;
	WHT_Data_t* WHT_Data;


	if (tx_message->length > sizeof(TxMessage.Data))
	{
		return ERROR;
	}
	
	if (name == CAN_1)
	{
		WHT_Data = &WHT_CAN1;
	}
	else if (name == CAN_2)
	{
		WHT_Data = &WHT_CAN2;
	}
	else
	{
		return ERROR;
	}
	
	WHT_Data->Info.TRx_State = CAN_TRx_Busy;

	TxMessage.StdId = tx_message->ID;
	TxMessage.ExtId = tx_message->ID;
	TxMessage.RTR = CAN_RTR_Data;
	TxMessage.IDE = CAN_Id_Standard; //CAN_Id_Standard 标准帧 CAN_Id_Extended 扩展帧
	TxMessage.DLC = tx_message->length;
	memcpy(TxMessage.Data, tx_message->buffer, tx_message->length);

	CAN_ITConfig((CAN_TypeDef*)name, CAN_IT_TME, ENABLE); //发送邮箱空中断
    // 发送CAN消息 (触发第一次发送)
	if (CAN_Transmit(CAN1, &TxMessage) == CAN_TxStatus_NoMailBox)
	{
		WHT_Data->Info.TRx_Error_State = CAN_Tx_Error;
		WHT_Data->Info.TRx_State = CAN_TRx_Idle;
		return ERROR; // 发送失败
    }
	else
	{
		return SUCCESS; // 发送成功
	}
}



/*全局常量*/
const WHT_CAN_BSP_t WHT_CAN_BSP =
{
	.WHT_CAN1_Info    = &WHT_CAN1.Info,
	.WHT_CAN2_Info    = &WHT_CAN2.Info,
	.WHT_Config       = WHT_CAN_BSP_Config,
	.WHT_TxMessage    = WHT_CAN_BSP_TxMessage,
	.WHT_TxMessage_IT = WHT_CAN_BSP_TxMessage_IT,
};





/* CAN1 发送中断服务程序 */
void CAN1_TX_IRQHandler(void)
{
    if (CAN_GetITStatus(CAN1, CAN_IT_TME) != RESET)
	{
        // 清除中断标志
        CAN_ClearITPendingBit(CAN1, CAN_IT_TME);

        // 识别哪个邮箱发送完成
        if(CAN_GetFlagStatus(CAN1, CAN_FLAG_RQCP0) != RESET)
		{
            CAN_ClearFlag(CAN1, CAN_FLAG_RQCP0); // 清除邮箱0请求完成标志
            // 处理邮箱0发送完成的操作
        }
        
        if(CAN_GetFlagStatus(CAN1, CAN_FLAG_RQCP1) != RESET)
		{
            CAN_ClearFlag(CAN1, CAN_FLAG_RQCP1); // 清除邮箱1请求完成标志
            // 处理邮箱1发送完成的操作
        }
        
        if(CAN_GetFlagStatus(CAN1, CAN_FLAG_RQCP2) != RESET)
		{
            CAN_ClearFlag(CAN1, CAN_FLAG_RQCP2); // 清除邮箱2请求完成标志
            // 处理邮箱2发送完成的操作
        }

		WHT_CAN1.Info.TRx_State = CAN_TRx_Idle;
		if (WHT_CAN1.Tx_IT_Callback)
		{
			WHT_CAN1.Tx_IT_Callback();
		}
    }
}

/* CAN1 接收中断服务程序 */
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	static CanRxMsg RxMessage;

	if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)
	{
		CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
		if (WHT_CAN1.Rx_IT_Callback)
		{
			WHT_CAN1.Rx_IT_Callback(RxMessage.IDE == CAN_Id_Standard ? RxMessage.StdId : RxMessage.ExtId, RxMessage.Data, RxMessage.DLC);
		}
		CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
	}
}


// CAN错误中断服务函数
void CAN1_SCE_IRQHandler(void)
{
    // 按优先级顺序处理错误（BOF > EPV > EWG > LEC）
    if (CAN_GetITStatus(CAN1, CAN_IT_BOF) != RESET)
	{
		/* 总线关闭错误处理（最高优先级） */
		// CAN控制器关闭
		CAN_DeInit(CAN1);

		// 更新错误状态
		WHT_CAN1.Info.Error_State.error_count++;
		WHT_CAN1.Info.Error_State.error_bof_count++;
		WHT_CAN1.Info.Error_State.is_bus_off = ENABLE;

        CAN_ClearITPendingBit(CAN1, CAN_IT_BOF);
    }
    else if (CAN_GetITStatus(CAN1, CAN_IT_EPV) != RESET)
	{
		/* 错误被动状态处理 */
		// 更新错误状态
		WHT_CAN1.Info.Error_State.error_count++;
		WHT_CAN1.Info.Error_State.error_epv_count++;
		WHT_CAN1.Info.Error_State.is_error_passive = ENABLE;

		// 执行降级策略（如降低发送频率、增加重传次数）应用层处理

        CAN_ClearITPendingBit(CAN1, CAN_IT_EPV);
    }
    else if (CAN_GetITStatus(CAN1, CAN_IT_EWG) != RESET)
	{
		/* 错误警告处理 */
		// 更新错误状态
		WHT_CAN1.Info.Error_State.error_count++;
		WHT_CAN1.Info.Error_State.error_ewg_count++;

		// 接近错误被动状态，应用层去处理

        CAN_ClearITPendingBit(CAN1, CAN_IT_EWG);
    }
    else if (CAN_GetITStatus(CAN1, CAN_IT_LEC) != RESET)
	{
		/* 最新错误码处理 */
		// 获取并记录具体错误码
		WHT_CAN1.Info.Error_State.last_error_code = CAN_GetLastErrorCode(CAN1);
		/*
		CAN_ErrorCode_NoErr          // 无错误（可能是错误已清除）
		CAN_ErrorCode_StuffErr       // 位填充错误
		CAN_ErrorCode_FormErr        // 格式错误
		CAN_ErrorCode_ACKErr         // ACK错误（无应答）
		CAN_ErrorCode_BitRecessiveErr// 位错误（发送1收到0）
		CAN_ErrorCode_BitDominantErr // 位错误（发送0收到1）
		CAN_ErrorCode_CRCErr         // CRC错误
		CAN_ErrorCode_SoftwareSetErr // 软件设置错误
		*/
		if (WHT_CAN1.Info.Error_State.last_error_code == CAN_ErrorCode_ACKErr)
		{
			printf("CAN No ACK\r\n");
		}
        CAN_ClearITPendingBit(CAN1, CAN_IT_LEC);
    }
}
